package com.jc.order.controller;


import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jc.constant.OperationTypeEnum;
import com.jc.order.service.impl.EciCustomerSaleApplyValidator;
import com.jc.order.constant.DataStatusEnum;
import com.jc.order.constant.ErrorCode;
import com.jc.order.dto.EciCustomerSaleApplyDTO;
import com.jc.order.dto.SystemTenantDTO;
import com.jc.order.service.ApiBaseService;
import com.jc.order.service.EciCustomerSaleApplyService;
import com.jc.order.util.DTOCompareUtil;
import com.jc.util.Result;
import com.jc.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 赊销申请
 */
@RestController
@RequestMapping("creditSale/v1")
@Slf4j
@Validated
public class EciCreditSaleController {
    private static final String LOG_PREFIX = "[CreditSale]";

    @Autowired
    private ApiBaseService apiBaseService;
    @Autowired
    private EciCustomerSaleApplyService eciCustomerSaleApplyService;
    @Autowired
    private EciCustomerSaleApplyValidator eciCustomerSaleApplyValidator;
    
    private final ObjectMapper objectMapper = new ObjectMapper();

    @RequestMapping("declareData")
    public Result<CreditSaleVO> declareData(@Valid @RequestBody OrderRequest request) {
        Result<CreditSaleVO> result = new Result<>();
        try {
            // 1. 验证基础信息
            SystemTenantDTO tenant = apiBaseService.validateBaseInfo(request, result);
            if (!result.getSuccess()) {
                log.warn("{} 基础信息验证失败: {}", LOG_PREFIX, result.getMessage());
                return result;
            }

            // 2. 转换请求数据
            CreditSaleVO creditSaleVO = parseDTO(request.getData(), result);
            if (!result.getSuccess()) {
                log.warn("{} 数据转换失败: {}", LOG_PREFIX, result.getMessage());
                return result;
            }

            // 3. 业务处理
            EciCustomerSaleApplyDTO dto = buildCustomerSaleApplyDTO(creditSaleVO, tenant);
            List<String> errors = eciCustomerSaleApplyValidator.validate(dto);
            if (!errors.isEmpty()) {
                result.error(ErrorCode.VALIDATION_FAILED, "数据校验未通过");
                log.warn("{} 数据校验失败: {}", LOG_PREFIX, errors);
                return buildErrorResponse(result, creditSaleVO, errors);
            }

            processByOperationType(dto, result);
            return buildResponse(result, creditSaleVO, dto);
        } catch (Exception e) {
            log.error("{} 系统异常: ", LOG_PREFIX, e);
            result.error().setMessage("系统处理异常，请稍后重试");
            return result;
        }
    }

    private EciCustomerSaleApplyDTO buildCustomerSaleApplyDTO(CreditSaleVO creditSaleVO, SystemTenantDTO tenant) {
        EciCustomerSaleApplyDTO dto = new EciCustomerSaleApplyDTO();
        BeanUtils.copyProperties(creditSaleVO, dto);
        dto.setTenantId(tenant.getId());
        dto.setDataStatus(DataStatusEnum.DATA_STATUS_1.getCode());
        return dto;
    }

    private Result<CreditSaleVO> buildErrorResponse(Result<CreditSaleVO> result, CreditSaleVO creditSaleVO, List<String> errors) {
        CreditSaleResponse response = new CreditSaleResponse();
        response.setErrors(errors);
        creditSaleVO.setResponse(response);
        result.setContent(creditSaleVO);
        return result;
    }

    private void processByOperationType(EciCustomerSaleApplyDTO dto, Result<?> result) {
        OperationTypeEnum operationType = OperationTypeEnum.getByCode(dto.getOperationType());
        switch (operationType) {
            case NEW:
                processNewInsuranceFlow(dto, result);
                break;
            case MODIFY:
                processModifyInsuranceFlow(dto, result);
                break;
            case CHANGE:
                //processModifyInsuranceFlow(dto, result);
                break;
            default:
                result.error(ErrorCode.INVALID_OPERATION_TYPE, "操作类型(operationType)只能填写[NEW,MODIFY]");
        }
    }

    private Result<CreditSaleVO> buildResponse(Result<CreditSaleVO> result, CreditSaleVO creditSaleVO, EciCustomerSaleApplyDTO dto) {
        CreditSaleResponse response = new CreditSaleResponse();
        response.setCorpSerialNo(dto.getCorpSerialNo());
        response.setDataStatus(dto.getDataStatus());
        creditSaleVO.setResponse(response);
        result.setContent(creditSaleVO);
        return result;
    }

    @RequestMapping("query")
    public Result<List<CreditSaleVO>> queryQuotaApproved(@RequestBody OrderRequest request) {
        Result<List<CreditSaleVO>> result = new Result<>();
        try {
            // 1. 基础信息验证
            SystemTenantDTO tenant = apiBaseService.validateBaseInfo(request, result);
            if (!result.getSuccess()) {
                return result;
            }

            // 2. 参数解析与校验
            List<String> snNoList = parseSnNos(request.getData());
            if (CollectionUtils.isEmpty(snNoList)) {
                return new Result().error(ErrorCode.QUERY_PARAM_MISSING, "缺少关键查询参数 corpSerialNos");
            }
            if (snNoList.size() > 500) {
                return new Result().error(ErrorCode.QUERY_TOO_LARGE, "查询数据量过大，请拆分多次请求");
            }

            // 3. 数据查询
            List<EciCustomerSaleApplyDTO> dtoList = eciCustomerSaleApplyService.getBySerialNoList(snNoList, tenant.getId());
            if (CollectionUtils.isEmpty(dtoList)) {
                return new Result().ok(Collections.emptyList());
            }

            // 4. 构建响应
            return new Result().ok(buildQuotaResponse(dtoList, tenant.getId()));
        } catch (Exception e) {
            log.error("限额查询系统异常: request={}", request, e);
            return new Result().error("系统处理异常，请稍后重试");
        }
    }


    private List<CreditSaleVO> buildQuotaResponse(List<EciCustomerSaleApplyDTO> applyList, Long tenantId) {

        return applyList.stream().map(applyDTO -> {
            CreditSaleVO vo = new CreditSaleVO();
            BeanUtils.copyProperties(applyDTO, vo);
            CreditSaleResponse response = new CreditSaleResponse();
            response.setCorpSerialNo(applyDTO.getCorpSerialNo());
            response.setDataStatus(applyDTO.getDataStatus());
            response.setPremium(applyDTO.getPremium());
            response.setRate(applyDTO.getRate());
            vo.setResponse(response);
            return vo;
        }).collect(Collectors.toList());
    }


    // 解析snNos参数
    protected List<String> parseSnNos(String data) throws JsonProcessingException {
        if (StrUtil.isEmpty(data)) return Collections.emptyList();

        Map<String, String> map = objectMapper.readValue(data, new TypeReference<Map<String, String>>() {
        });
        String snNos = map.get("corpSerialNos");
        if (StrUtil.isEmpty(snNos)) return Collections.emptyList();

        return Arrays.stream(snNos.split(","))
                .filter(StrUtil::isNotBlank)
                .collect(Collectors.toList());
    }


    /**
     * 数据转换
     *
     * @param jsonData
     * @param result
     * @return
     */
    private CreditSaleVO parseDTO(String jsonData, Result result) {

        try {
            CreditSaleVO applyVO = objectMapper.readValue(jsonData, new TypeReference<CreditSaleVO>() {
            });
            return applyVO;
        } catch (JsonProcessingException e) {
            log.error("请求数据解析失败: {}", jsonData, e);
            result.error(ErrorCode.DATA_PARSE_ERROR, "数据格式错误");
            return null;
        }
    }


    private void processNewInsuranceFlow(EciCustomerSaleApplyDTO dto, Result result) {
        // 检查重复订单
        List<EciCustomerSaleApplyDTO> existingList = eciCustomerSaleApplyService.selectSaleApply(dto);
        if (existingList != null && existingList.size() > 0) {
            EciCustomerSaleApplyDTO existing = existingList.get(0);
            if (existing.getCorpSerialNo().equalsIgnoreCase(dto.getCorpSerialNo())) {
                result.error(ErrorCode.DUPLICATE_APPLICATION, "流水号[" + dto.getCorpSerialNo() + "] 已存在,请勿重复");
            } else if (existing.getContractNo().equalsIgnoreCase(dto.getContractNo())) {
                result.error(ErrorCode.DUPLICATE_APPLICATION, "发票号[" + dto.getContractNo() + "] 已存在,请勿重复");
            }
        }
        if (!result.getSuccess()) {
            return;
        }
        //数据保存
        eciCustomerSaleApplyService.insertDeclareData(dto);
        if (dto.getId() != null) {
            result.ok();
        } else {
            result.error();
        }
    }

    //修改数据申报
    private void processModifyInsuranceFlow(EciCustomerSaleApplyDTO dto, Result result) {
        //1.根据流水号查询申报数据
        EciCustomerSaleApplyDTO old = eciCustomerSaleApplyService.selectByCorpSerialNo(dto.getCorpSerialNo(), dto.getTenantId());
        if (old == null) {
            result.error(ErrorCode.RECORD_NOT_FOUND, "流水号[" + dto.getCorpSerialNo() + "] 不已存在,请确认再进行操作");
        } else {
            if (!DataStatusEnum.DATA_STATUS_REFUSE.getCode().equalsIgnoreCase(old.getDataStatus())) {
                result.error(ErrorCode.INVALID_STATUS, "流水号[" + dto.getCorpSerialNo() + "] 当前状态不能进行操作");
            }
            // 校验发票号
            EciCustomerSaleApplyDTO q=new EciCustomerSaleApplyDTO();
            q.setTenantId(dto.getTenantId());
            q.setContractNo(dto.getContractNo());
            List<EciCustomerSaleApplyDTO> existingList = eciCustomerSaleApplyService.selectSaleApply(q);

        }
        if (!result.getSuccess()) {
            return;
        }
        dto.setId(old.getId());
        dto.setCreateTime(old.getCreateTime());
        dto.setCreateUser(old.getCreateUser());
        List<DTOCompareUtil.FieldChange> list = DTOCompareUtil.compareObjectChanges(old, dto);
        if (list != null && list.size() > 0) {
            eciCustomerSaleApplyService.updateCustomerSaleApply(dto);
            for (int i = 0; i < list.size(); i++) {
                DTOCompareUtil.FieldChange fieldChange = list.get(i);
                log.info(fieldChange.toString());
            }
            result.ok();
        } else {
            result.error(ErrorCode.NO_CHANGES_DETECTED, "没有监测到修改属性，无需提交");
        }
    }
}
